﻿Imports System.Windows.Media.Imaging
Imports System.Reflection
Imports System.Globalization
Imports System.IO
Imports Co9320.NamaAlert.Model
Imports System.Collections.ObjectModel
Imports System.ComponentModel

Namespace ViewModel

    Public Class StationViewModel
        Inherits ViewModelBase

        Private Model As Model.Station
        Public Sub New(ByVal model As Model.Station)
            Me.Model = model
        End Sub

        Public Function ToModel() As Model.Station
            Model.PluginGuids.Clear()
            For Each a In AlertManners
                If a.IsEnabled Then
                    Model.PluginGuids.Add(a.Plugin.Guid)
                End If
            Next
            Return Model
        End Function

#Region "Wrapper"

        Public ReadOnly Property Id() As String
            Get
                Return Model.Id
            End Get
        End Property

        Public ReadOnly Property Name() As String
            Get
                Return Model.Name
            End Get
        End Property

        Public ReadOnly Property UpdateDateTime() As DateTime
            Get
                Return Model.UpdateDateTime
            End Get
        End Property

        Public ReadOnly Property Uri() As Uri
            Get
                Return Model.Uri
            End Get
        End Property

        Public ReadOnly Property Kind() As StationKind
            Get
                Return Model.Kind
            End Get
        End Property

        Public Property Level() As Integer
            Get
                Return Model.Level
            End Get
            Set(ByVal value As Integer)
                Model.Level = value
                OnPropertyChanged("Level")
            End Set
        End Property

        Public Property MemberCount() As Integer
            Get
                Return Model.MemberCount
            End Get
            Set(ByVal value As Integer)
                Model.MemberCount = value
                OnPropertyChanged("MemberCount")
            End Set
        End Property

        Public Property Rating() As Integer
            Get
                Return Model.Rating
            End Get
            Set(ByVal value As Integer)
                If value < 0 Then
                    Model.Rating = 0
                ElseIf value > 5 Then
                    Model.Rating = 5
                Else
                    Model.Rating = value
                End If
                IsChanged = True
                OnPropertyChanged("Rating")
            End Set
        End Property

        Public Property IsAlertTarget() As Boolean
            Get
                Return Model.IsAlertTarget
            End Get
            Set(ByVal value As Boolean)
                Model.IsAlertTarget = value
                IsChanged = True
                OnPropertyChanged("IsAlertTarget")
            End Set
        End Property

        Public Property Note() As String
            Get
                Return Model.Note
            End Get
            Set(ByVal value As String)

            End Set
        End Property

#End Region

        Private _IsChanged As Boolean
        Public Property IsChanged() As Boolean
            Get
                Return _IsChanged
            End Get
            Set(ByVal value As Boolean)
                _IsChanged = value
                OnPropertyChanged("IsChanged")
            End Set
        End Property

        'Private AlertMannersSyncObject As New Object

        Public Sub RefreshAlertManners(ByVal plugins As IList(Of PluginViewModel), ByVal enabledGuids As IList(Of Guid))
            'SyncLock AlertMannersSyncObject
            'Debug.Print("RefreshAlertManners: {0}", System.Threading.Thread.CurrentThread.ManagedThreadId)

            If _AlertManners Is Nothing Then
                _AlertManners = New ObservableCollection(Of AlertMannerViewModel)
            Else
                AlertManners.Clear()
            End If

            'Dim guids = From a In AlertManners Where a.IsEnabled Select a.Plugin.Guid
            For Each p In From plugin In plugins Where plugin.HasAlertFunction AndAlso plugin.IsEnabled
                Dim am = New AlertMannerViewModel With {.Plugin = p}
                If enabledGuids.Contains(p.Guid) Then
                    am.IsEnabled = True
                End If
                AlertManners.Add(am)
            Next

            'End SyncLock

            OnPropertyChanged("AlertManners")
        End Sub

        Public Sub EnablePlugin(ByVal pluginGuid As Guid)

            Dim manners = From a In AlertManners Where a.Plugin.Guid = pluginGuid
            If manners.Count > 0 Then
                manners.SingleOrDefault.IsEnabled = True
            End If

        End Sub

        Private WithEvents _AlertManners As ObservableCollection(Of AlertMannerViewModel)
        Public Property AlertManners() As ObservableCollection(Of AlertMannerViewModel)
            Get
                Return _AlertManners
            End Get
            Set(ByVal value As ObservableCollection(Of AlertMannerViewModel))
                ' MEMO For DataGrid editor
                _AlertManners = value
            End Set
        End Property

        Private Sub _AlertManners_CollectionChanged(ByVal sender As Object, ByVal e As System.Collections.Specialized.NotifyCollectionChangedEventArgs) Handles _AlertManners.CollectionChanged
            If e.NewItems IsNot Nothing Then
                For Each i In e.NewItems
                    AddHandler DirectCast(i, AlertMannerViewModel).PropertyChanged, AddressOf AlertManner_PropertyChanged
                Next
            End If
            If e.OldItems IsNot Nothing Then
                For Each i In e.OldItems
                    RemoveHandler DirectCast(i, AlertMannerViewModel).PropertyChanged, AddressOf AlertManner_PropertyChanged
                Next
            End If
        End Sub

        Private Sub AlertManner_PropertyChanged(ByVal sender As Object, ByVal e As PropertyChangedEventArgs)
            IsChanged = True
        End Sub

#Region "Icon"

        Private _ForceIcon As Boolean
        Public Property ForceIcon() As Boolean
            Get
                Return _ForceIcon
            End Get
            Set(ByVal value As Boolean)
                _ForceIcon = value
                OnPropertyChanged("ForceIcon")
            End Set
        End Property

        Private Shared _CachePath As String = System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly.Location)
        Public Shared Property CachePath() As String
            Get
                Return _CachePath
            End Get
            Set(ByVal value As String)
                Try
                    My.Computer.FileSystem.CreateDirectory(value)
                Catch ex As IOException

                End Try
                _CachePath = value
            End Set
        End Property

        Private ReadOnly Property CachedIconPath() As String
            Get
                Return System.IO.Path.Combine(StationViewModel.CachePath, Me.Id & ".jpg")
            End Get
        End Property

        Private WithEvents WebClient As System.Net.WebClient

        Private ReadOnly Property CachedIcon() As BitmapImage
            Get
                If ForceIcon Then
                    Return Nothing
                End If

                Dim icon As BitmapImage = Nothing

                If System.IO.File.Exists(Me.CachedIconPath) Then
                    Dim info = New System.IO.FileInfo(Me.CachedIconPath)

                    Try
                        icon = New BitmapImage(New Uri(Me.CachedIconPath))

                        ' 更新
                        If info.LastWriteTime.AddHours(3) < Now Then
                            DownloadIconAsync()
                        End If

                    Catch fileNotFoundEx As System.IO.FileNotFoundException
                        ' Ignore
                    Catch ex As Exception
                        ' Ignore
                    End Try
                Else
                    DownloadIconAsync()
                End If

                If icon Is Nothing Then
                    Return StationViewModel.NoImageIcon
                Else
                    Return icon
                End If
            End Get
        End Property

        Private Sub DownloadIconAsync()
            WebClient = New System.Net.WebClient
            WebClient.DownloadFileAsync(Model.IconUri, Me.CachedIconPath)
        End Sub

        Private _Icon As BitmapImage
        Public ReadOnly Property Icon() As ImageSource
            Get
                If _Icon Is Nothing Then
                    _Icon = Me.CachedIcon
                End If
                Return _Icon
            End Get
        End Property

        Private Shared _NoImageIcon As BitmapImage
        Private Shared ReadOnly Property NoImageIcon() As BitmapImage
            Get
                If _NoImageIcon Is Nothing Then
                    Dim noimageUri = New Uri("pack://application:,,,/NamaAlert;component/Images/noimage.jpg")
                    _NoImageIcon = New BitmapImage(noimageUri)
                End If
                Return _NoImageIcon
            End Get
        End Property

        Private Sub WebClient_DownloadFileCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.AsyncCompletedEventArgs) Handles WebClient.DownloadFileCompleted

            WebClient.Dispose()
            WebClient = Nothing

            If e.Cancelled Then
                Exit Sub
            End If

            Try
                If System.IO.File.Exists(Me.CachedIconPath) Then
                    Dim info = New System.IO.FileInfo(Me.CachedIconPath)
                    If info.Length = 0 Then

                        Try
                            System.IO.File.Delete(Me.CachedIconPath)

                        Catch dirEx As DirectoryNotFoundException
                            ' Ignore
                        Catch ioEx As IOException
                            ' Ignore
                        Catch unauthEx As UnauthorizedAccessException
                            ' Ignore
                        End Try

                    Else
                        Try
                            _Icon = New BitmapImage(New Uri(Me.CachedIconPath))
                            OnPropertyChanged("Icon")
                        Catch fileNotFoundEx As System.IO.FileNotFoundException
                            ' Ignore
                        Catch ex As Exception
                            ' Ignore
                        End Try
                    End If
                End If

            Catch ex As Exception
                Debug.Assert(False) ' Stop  
            End Try

        End Sub

        Protected Overrides Sub Dispose(ByVal disposing As Boolean)
            Try
                If WebClient IsNot Nothing Then
                    If WebClient.IsBusy Then
                        WebClient.CancelAsync()
                    End If
                    WebClient.Dispose()
                End If
            Catch ex As Exception
                ' Ignore
            End Try
            MyBase.Dispose(disposing)
        End Sub

#End Region


    End Class

End Namespace